#include <strings.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>

#include "TcpServer.h"
#include "WebServer.h"
#include "HeaderParse.h"
#include "Global.h"
#include "FileInfo.h"

//bug是由于客户端向服务器发送的数据的cookie数据中，没有\r\n\r\n换行符，导致HeaderParse::HeaderParse(const char *header)
//函数中20行没有判断出\r\n\r\n，导致HeaderParse::HeaderParse(const char *header)函数中第68行在pLine=NULL的情况下没有break，
//从而在while中没有‘:‘字符而一直循环

WebServer::WebServer(short port, int maxlisten):
TcpServer(port, maxlisten)
{
    DEBUG_LOG("WebServer::WebServer()");
}

WebServer::~WebServer()
{
    DEBUG_LOG("WebServer::~WebServer()");
}

void 
WebServer::notFound(int clientsock)
{
    DEBUG_LOG("WebServer::notFound()");

    char path[100];
    strcpy(path, FILEPATH);
    strcat(path,"/notfound.html");

    struct stat statbuff;
    unsigned long  filesize = 0;
    if(-1 != stat(path, &statbuff))
    {  
        filesize = statbuff.st_size;
    }
    else
    {
        ERROR_LOG("%s",path);
    }

    char buf[100];
    sprintf(buf, "HTTP/1.1 404 NOT FOUND\r\n");
    write(clientsock, buf, strlen(buf));
    sprintf(buf, "Server: Girl/0.1.0\r\n");
    write(clientsock, buf, strlen(buf));
    sprintf(buf, "Content-Type: text/html\r\n");
    write(clientsock, buf, strlen(buf));
    sprintf(buf, "Content-Length: %ld\r\n",filesize);
    write(clientsock, buf, strlen(buf));
    sprintf(buf, "\r\n");
    write(clientsock, buf, strlen(buf));
    sendFile(clientsock, path);
}

void 
WebServer::notImplement(int clientsock)
{
    DEBUG_LOG("WebServer::notImplement()");

    char path[100];
    strcpy(path, FILEPATH);
    strcat(path,"/notimplemented.html");

    struct stat statbuff;
    unsigned long  filesize = 0;
    if(-1 != stat(path, &statbuff))
    {  
        filesize = statbuff.st_size;
    }
    else
    {
        ERROR_LOG("%s",path);
    }

    char buf[100];
    sprintf(buf, "HTTP/1.1 404 NOT FOUND\r\n");
    write(clientsock, buf, strlen(buf));
    sprintf(buf, "Server: Girl/0.1.0\r\n");
    write(clientsock, buf, strlen(buf));
    sprintf(buf, "Content-Type: text/html\r\n");
    write(clientsock, buf, strlen(buf));
    sprintf(buf, "Content-Length: %ld\r\n",filesize);
    write(clientsock, buf, strlen(buf));
    sprintf(buf, "\r\n");
    write(clientsock, buf, strlen(buf));
    sendFile(clientsock, path);
}

void 
WebServer::sendHeader(int clientsock, FileInfo &HInfo)
{
    DEBUG_LOG("WebServer::sendHeader()");

    char buf[1024];
    strcpy(buf, "HTTP/1.1 200 OK\r\n");
    write(clientsock, buf, strlen(buf));

    strcpy(buf, "Server: Girl/0.1.0\r\n");
    write(clientsock, buf, strlen(buf));

    strcpy(buf, "Connection: Keep-Alive\r\n");
    write(clientsock, buf, strlen(buf));

    sprintf(buf, "Content-Type: %s\r\n",HInfo.getFileType());
    write(clientsock, buf, strlen(buf));

    sprintf(buf, "Content-Length: %ld\r\n",HInfo.getFileSize());
    write(clientsock, buf, strlen(buf));

    strcpy(buf, "\r\n");
    write(clientsock, buf, strlen(buf));
}

bool 
WebServer::sendFile(int clientsock, const char *Path)
{
    DEBUG_LOG("WebServer::sendFile()\t%s", Path);
    char buf[1024];
    int fp;
    if(-1 == (fp=open(Path, O_RDONLY)))
    {
    	ERROR_LOG("%s",Path);
    	return false;
    }
    int n; 
    while((n = read(fp, buf, 1024)) != 0)
    {
        if(n > 0)
        {
            if (-1 == write(clientsock, buf, n))
            {
                ERROR_LOG("Clientsock:%d",clientsock);
                return false;
            }
        }
        else
        {
            ERROR_LOG("%s",Path);
            return false;
        }
    }
    close(fp);
    return true;
}

bool 
WebServer::doGet(int clientsock, HeaderParse &Hparse)
{
    DEBUG_LOG("WebServer::doGet()");
    char buf[1000];
    char Path[500];
    Hparse.getPath(Path);
    int filestatus;
    if(-1 != access(Path, F_OK)) //File exists?
    {
        FileInfo HInfo(Path);
        sendHeader(clientsock, HInfo);
        if(false == sendFile(clientsock, Path))
        {
            return false;
        }
    }
    else
    {  
        ERROR_LOG("%s",Path);
        notFound(clientsock);
        return false;
    } 

    return true;
}

bool 
WebServer::doPost(int clientsock, HeaderParse &Hparse)
{
    notImplement(clientsock);
    return true;
}

void
WebServer::onAccept(Clientinfo *info)
{
    DEBUG_LOG("WebServer::onAccept()");
    int clientsock = info->sock;
    struct sockaddr_in clienaddr = info->clienaddr;
    char readBuf[4096];
    while(true)
    {
        bzero(readBuf, HEADER_SIZE);
        //DEBUG_LOG("start read");
        int n = read(clientsock, readBuf, 4096);
        //DEBUG_LOG("read ok");
        //printf("%s\n",readBuf);
        if(n <= 0)
        {
            close(clientsock);
            break;
        }
        else
        {
            char Method[10];

            HeaderParse Hparse(readBuf);
            Hparse.getMethod(Method);
            //DEBUG_LOG("Method:%s",Method);
            if(0 == strcmp(Method, "GET"))
            {
                if(false == doGet(clientsock, Hparse))
                {
                   close(clientsock);
                   return ;
                }
                // doGet(clientsock, Hparse);
                // close(clientsock);
                // return ;
            }
            else if(0 == strcmp(Method, "POST"))
            {
                doPost(clientsock, Hparse);
            }
            else
            {

            }
        }
    }
}

int main()
{
    WebServer T(8888, 10);
    T.start();
    while(1)
    {
        sleep(1000);
        //DEBUG_LOG("Number of threads:%d", TcpServer::m_currentconnect);
    }
    return 0;
}
